package com.hb.bussiness.utils;

import com.hb.common.utils.SpringUtil;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * @author
 * @date:2023/4/3 18:56
 * 生成唯一编号工具
 */

@Component
public class GenerateUtils implements InitializingBean {

    @Autowired
    @Qualifier("stringRedisTemplate")
    private RedisTemplate<String, String> redisTemplate;

    public static GenerateUtils generateUtils;

    /**
     * 生成备案编号
     *
     * @param moduleName 模块名称
     * @param now        现在
     * @return {@link String}
     */
    public static String generateRecordNo(String moduleName, Date now) {

        if (Objects.isNull(now)) {
            now = new Date();
        }
        String yyyyMMdd = DateFormatUtils.format(now, "yyyyMMdd");
        Long serialNumber = generateUtils.getSerialNumber(moduleName, yyyyMMdd);

        //ZYRZ 20220301 -1
        StringBuilder sb = new StringBuilder("");

        sb.append(moduleName).append(yyyyMMdd)
                .append("-").append(serialNumber);

        return sb.toString();
    }

    public Long getSerialNumber(String moduleName, String yyyyMMdd) {

        String cacheKey = moduleName + yyyyMMdd;
        Long secondsNextEarlyMorning = getSecondsNextEarlyMorning();

        //先查找有无该值，有则+1并返回， 无则设置1并返回
        String script =
                "if redis.call('EXISTS', KEYS[1]) == 0 then \n" +
                "   redis.call('SET', KEYS[1], ARGV[1]); \n" +
                "   redis.call('expire', KEYS[1], ARGV[2]); \n"+
                "   return 1;\n" +
                "else\n" +
                "   local current = tonumber(redis.call('INCR', KEYS[1])); \n" +
                "   redis.call('expire', KEYS[1], ARGV[2]); \n"+
                "   return current; \n"+
                "end;";
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Long.class);
        redisScript.setScriptText(script);

        Long value = redisTemplate.execute(redisScript, Arrays.asList(cacheKey),
                String.valueOf(1), String.valueOf(secondsNextEarlyMorning));
        return value;
    }


    /**
     * 获取当前时间距离今晚12点的秒数
     * @return
     */
    public static Long getSecondsNextEarlyMorning() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
    }

    @Override
    public void afterPropertiesSet() {
        generateUtils = SpringUtil.getBean(GenerateUtils.class);
    }
}
